<!DOCTYPE html>
<html>
<head>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type">
    <title>动画</title>
    <script type="text/javascript" src="../jquery-1.6.2.js"></script>
    <style type="text/css">
        #an {
            width: 100px;
            height: 120px; background: #3300ff; margin-left: 10px; position: absolute;
        }
    </style>
</head>
<body>
<button class="btn" id="start">开始</button>
<button class="btn" id="stop">停止</button>
<button class="btn" id="reverse">倒退</button>
<div style="height: 40px;"></div>
<div id="an">

</div>

<script type="text/javascript">

    function Anim(elem) {
        this.timeID = 0;
        this.elem = elem;
    }
    Anim.prototype = {
        run:function(oTargetStyle, duration) {
            //margin-left->marginLeft, 10px->10

            oTargetStyle = this._turn(oTargetStyle, 'hump');

            //获得初始样式
            var oInitStyle = this._getStyle(oTargetStyle),
                    oChangeStyle = this._getChangeStyle(oTargetStyle, oInitStyle);
            this._exec(oTargetStyle, oInitStyle, oChangeStyle, duration);
        },
        stop:function() {
            clearInterval(this.timeID);
        },

        _exec:function(oTargetStyle, oInitStyle, oChangeStyle, duration) {
            var _this = this;
            var oTmpStyle = {};
            var FRAMES = 60,iMILL = 1000 / FRAMES;
            var t = 0,b = 0, c = 0, d = duration;
            this.timeID = setInterval(function() {
                t += iMILL;
                for (var sKey in oInitStyle) {
                    c = oChangeStyle[sKey];
                    b = oInitStyle[sKey];
                    oTmpStyle[sKey] = t * c / d + b;
                }
                _this._setStyle(oTmpStyle);

                if (t >= d) {
                    clearInterval(_this.timeID);
                    _this._setStyle(oTargetStyle);
                }

            }, iMILL);
        },
        _getChangeStyle:function(oStyle, oInitStyle) {
            var oTmp = {};
            for (var sKey in oStyle) {
                oTmp[sKey] = oStyle[sKey] - oInitStyle[sKey];
            }
            return oTmp;
        },
        _turn:function(oStyle, mode) {
            var oTmpStyle = {},sTmpKey,sKey;

            for (sKey in oStyle) {
                if (mode === 'hump') {
                    sTmpKey = sKey.indexOf('-') > 1 ? sKey.replace(/-\w/, function(w) {
                        w = w.substring(1).toUpperCase();
                        return w;
                    }) : sKey;
                    oTmpStyle[sTmpKey] = parseInt(oStyle[sKey], 10) || 0;
                } else {
                    oStyle[sKey] = typeof oStyle[sKey] == 'number' ? oStyle[sKey] + 'px' : oStyle[sKey];
                    sTmpKey = sKey.replace(/([A-Z])/, function(w) {
                        w = '-' + w.toLowerCase();
                        return w;
                    });
                    oTmpStyle[sTmpKey] = oStyle[sKey];
                }

            }

            return oTmpStyle;
        },
        _setStyle:function(oStyle) {
            var sCssText = '';
            oStyle=this._turn(oStyle,'use');
            for (var sKey in oStyle) {
                sCssText += sKey + ':' + oStyle[sKey] + ';';
            }
            this.elem.style.cssText = sCssText;
        },
        _getStyle:function(oStyle) {
            var oTmpStyle = {};
            for (var sKey in oStyle) {

                oTmpStyle[sKey] = (function(elem, key) {
                    if (window.getComputedStyle) {
                        return  parseInt(window.getComputedStyle(elem, null)[key], 10) || 0;
                    } else {
                        var oRect = elem.getBoundingClientRect();
                        if (key === 'width') {
                            return oRect.right - oRect.left;
                        } else if (key === 'height') {
                            return oRect.bottom - oRect.top;
                        }
                        return parseInt(elem.currentStyle[key], 10) || 0;
                    }
                })(this.elem, sKey);
            }
            return oTmpStyle;
        }
    };
    var an = document.getElementById('an');
    var start = document.getElementById('start');
    var stop = document.getElementById('stop');
    var reverse = document.getElementById('reverse');
    var oAnim = new Anim(an);
    var oAnimr = new Anim(reverse);
    //
    start.onclick = function() {
        oAnim.run({  width:1220}, 1000);
        // oAnimr.run({'margin-top':100}, 1000);
    }
    stop.onclick = function() {
        oAnim.stop();
    }
    reverse.onclick = function() {
        oAnim.revert();
    }
    //$(an).animate({width:1220},1000)

</script>
</body>
</html>